<?php

namespace app\command;

use think\facade\Log;
use think\worker\Server;
use Workerman\Lib\Timer;

class Test extends Server
{
    protected $protocol = 'websocket';
    protected $port     = '1316';
    protected $worker;
    protected $option   = [
        'name' => 'IM2',
        'count'=> 2,
        'uidConnections' => [],
    ];

    public function onWorkerStart(): void
    {
        $time_interval = 2;
        global $worker;
        Timer::add($time_interval, static function () use ($worker) {
            echo "心跳...".date("Y-m-d H:i:s")."\n";
        });

        $inner_text_worker = new \Workerman\Worker('text://127.0.0.1:1234');
        //这里的$connection是给推送者调用的
        $inner_text_worker->onMessage = static function ($connection, $buffer) {
            $connection->send( '你好欢迎你');
        };
        try {
            $inner_text_worker->listen();
        } catch (\Exception $e) {

        }
    }

    public function onMessage($connection,$data): bool
    {
        if (empty($data)){
            $connection->send('数据提交错误');
            return false;
        }
        //在控制台打印客户端发送过来的消息
        try {
            $data = json_decode($data, true, 512, JSON_THROW_ON_ERROR);
        } catch (\JsonException $e) {

        }
        if (!isset($data['room_id'], $data['type'],$data['uid'])){
            $connection->send('参数错误!');
            return false;
        }
        $checkInfo = self::checkLogin($data['uid']);
        if (empty($checkInfo)){
            $connection->send('登录失效重新登录!');
            return false;
        }

        switch ($data['type']) {
            //登录绑定
            case 'login':
                self::bind($data , $connection , $checkInfo);
                break;
            case 'sendLive':
                if (!isset($data['message'])){
                    $connection->send('输出输入错误!');
                    return  false;
                }
                //直播间聊天发消息
                self::sendMessageByLive($data['room_id'],$data['message'],$checkInfo);
                break;
        }
        return true;
    }

    public static function bind($data , $conn , $info): void
    {
        global $worker;
        $conn->roomId = $data['room_id'];
        $conn->uid  = $data['uid'];
        $conn->nick = $info['nick'];
        $worker->uidConnections[$conn->roomId][$conn->uid] = $conn;
        try {
            redis()->zAdd('LiveOnlineUsers:' . $conn->roomId, $conn->uid, json_encode($info, JSON_THROW_ON_ERROR));
            redis()->close();
            $conn->info = json_encode($info, JSON_THROW_ON_ERROR);
            foreach($worker->uidConnections[$conn->roomId] as $sen) {
                $sen->send($info['nick'].'进来了');
            }
        } catch (\JsonException $e) {
            Log::info('initJsonException'.$e->getMessage());
        } catch (\RedisException $e) {
            Log::info('RedisException'.$e->getMessage());
        }
    }

    public static function checkLogin($uid): array
    {
        try {
            $info = redis()->get('userInfo:'.$uid);
            if (empty($info)){
                return [];
            }
            try {
                $info = json_decode($info, true, 512, JSON_THROW_ON_ERROR);
                $info['id'] = $uid;
            } catch (\JsonException $e) {
                Log::info('InfoERROR'.$e->getMessage());
            }

            return $info;
        } catch (\RedisException $e) {
            Log::info('checkLoginRedisException'.$e->getMessage());
        }
        return [];
    }

    public static function sendMessageByLive($room_id, $message ,$info): bool{
        global $worker;
        if(empty($room_id) || empty($message)){
            return false;
        }
        //验证用户数据
        if (empty($info)){
            return  false;
        }
        //需要遍历在本直播间用户给每个用户推送聊天内容
        if (isset($worker->uidConnections[$room_id])){
            foreach ($worker->uidConnections[$room_id] as $connection) {
                $redisKey = 'imroomlog:'.$room_id;
                $setData = [
                    'uid'   => $info['id'],
                    'nick' => $info['nick'],
                    'content' => $message,
                    'toid' => $room_id,
                    'dates'=>date('Y-m-d H:i:s'),
                    'portrait'=>$info['portrait'],
                ];
                try {
                    try {
                        $redisData = json_encode($setData, JSON_THROW_ON_ERROR);
                    } catch (\JsonException $e) {
                        \think\facade\Log::info('Exception sendMessageByLiveEvent:JsonException' . $e->getMessage());
                    }
                    redis()->lPush($redisKey, $redisData);
                    redis()->close();
                } catch (\RedisException $e) {
                    \think\facade\Log::info('Exception sendMessageByLiveEvent: ' . $e->getMessage());
                }
                $connection->send($redisData);
            }
        }
        return false;
    }

    public function onError($connection): void
    {
        $connection->send('连接断开................'.date('Y-m-d H:i:s'));
        Log::info('Exception IM1Close:'.date('Y-m-d H:i:s'));
    }

    public function onClose($connection): void
    {
        global $worker;
        if (isset($connection->roomId)) {
            foreach ($worker->uidConnections[$connection->roomId] as $sen) {
                $sen->send($connection->nick . '走了');
            }
            //退出关闭链接
            if ($connection->uid) {
                try {
                    redis()->zRem('LiveOnlineUsers:' . $connection->roomId, $connection->info);
                    redis()->close();
                } catch (\RedisException $e) {
                    Log::info('Exception RedisException:'.date('Y-m-d H:i:s'));
                }
                unset($worker->uidConnections[$connection->roomId][$connection->uid]);
            }
        }
    }
}